
	var _all_script_objects = document.getElementsByTagName('script');
	var _current_script_object = _all_script_objects[_all_script_objects.length-1];
	var _current_audio_script_path = _current_script_object.src.replace(/\/audio-stream-player\.js$/, '/');

	function WebSocketAudioStreamPlayer () {
	
		this.Context = null;
		this.WorkerNode = null;
		this.Socket = null;

		this.Buffers = [];
		
		this.ChannelCount = 1;
		this.CurrentRemains = null;
		
		this.BufferSize = 1024;
		
		this.SetupBuffers = function(intputBuffer, remainBuffer, outputBuffers, outputBufferSize) {

			var totalInput = new Float32Array(intputBuffer.length + remainBuffer.length);
			totalInput.set(intputBuffer);
			if (remainBuffer.length > 0) totalInput.set(remainBuffer, intputBuffer.length);
			
			var outputRemainSize = totalInput.length % outputBufferSize;
			var outputBufferCount = (totalInput.length - outputRemainSize) / outputBufferSize;
			
			var beginPos = 0;
			for(var i=0; i<outputBufferCount; i++) {
				outputBuffers.push(totalInput.slice(beginPos, beginPos+outputBufferSize));
				beginPos = beginPos+outputBufferSize;
			}
			
			var finalRemain = null;
			if (outputRemainSize > 0) finalRemain = totalInput.slice(beginPos);
			else finalRemain = new Float32Array(0);
			
			return finalRemain;
		};
		
		this.WhenSocketConnected = function() {
			this.WorkerNode.connect(this.Context.destination);
		};
		
		this.WhenSocketGotMessage = function(event) {
		
			var data = event.data;

			if (typeof data != "string") {
		
				this.Context.decodeAudioData(data, function(buffer) {
				
					this.ChannelCount = buffer.numberOfChannels;
			
					var newbuffer = new Array();
					
					if (this.CurrentRemains == null) {
						this.CurrentRemains = new Array();
						for(var i=0; i<this.ChannelCount; i++) this.CurrentRemains.push(new Float32Array(0));
					}
					
					//console.log(this.BufferSize + " , " + this.Buffers.length);
					
					for (var i=0; i<this.ChannelCount; i++) {
										
						var intputBuffer = buffer.getChannelData(i);
						
						var remainBuffer = this.CurrentRemains[i];
						var outputBuffers = new Array();
						
						var finalRemain = this.SetupBuffers(intputBuffer, remainBuffer, outputBuffers, this.BufferSize);
						
						this.CurrentRemains[i] = finalRemain;
						newbuffer.push(outputBuffers);
					}
					
					var foundEmpty = false;
					while(!foundEmpty) {
					
						var usefulbuffers = new Array();
						for (var i=0; i<this.ChannelCount; i++) {
						
							if (newbuffer[i].length <= 0) {
								foundEmpty = true;
								break;
							}
							usefulbuffers.push(newbuffer[i].shift());
						}
						if (usefulbuffers.length == this.ChannelCount) this.Buffers.push(usefulbuffers);
					}
					
					if(this.Buffers.length > 0) this.WorkerNode.postMessage(this.Buffers);
					
					
				}.bind(this),
				function(err) {
					console.error('Audio decode error: ' + err);
				});
				
			}
		};
		
		this.Open = function(url, bufferSize) {
			
			if (!isNaN(bufferSize)) this.BufferSize = bufferSize;
			if (this.BufferSize < 1024) this.BufferSize = 1024;
			
			try {

				window.AudioContext = window.AudioContext       ||
									  window.webkitAudioContext ||
									  window.mozAudioContext    ||
									  window.oAudioContext      ||
									  window.msAudioContext;

				this.Context = new AudioContext();  //  cool audio context established

				this.WorkerNode = new AudioWorkerNode(this.Context, _current_audio_script_path + "audio-stream-process.js", 0, 1);
				
				this.WorkerNode.onmessage = function(event){
					if (this.Buffers != null && this.Buffers.length > 0) this.Buffers.shift();
				}.bind(this);
				
			} catch (e) {

				console.error(e);			
				var errorMsg = "Web Audio API or Web Worker is not supported by this browser";
				throw new Error(errorMsg);
			}

			this.Socket = new WebSocket(url);
			this.Socket.binaryType = "arraybuffer";
			
			this.Socket.onopen = this.WhenSocketConnected.bind(this);

			this.Socket.onmessage = this.WhenSocketGotMessage.bind(this);
	
		};
		
		this.Close = function() {
		
			if(this.Socket != null) this.Socket.close();
			
			if (this.WorkerNode != null) {
				this.WorkerNode.disconnect();
				this.WorkerNode.terminate();
			}
		
		};

	}
	
	
	